
package com.ld.security.server.admin.modules.ge.wrapper;

import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.mybatis.constant.*;
import com.ld.security.common.mybatis.util.TypeUtil;
import com.ld.security.common.mybatis.wrapper.AbstQueryWrapper;
import com.ld.security.common.mybatis.wrapper.SqlWrapper;
import com.ld.security.server.admin.modules.ge.constant.GeFieldConstant;
import com.ld.security.server.admin.modules.ge.entity.GeFieldEntity;
import com.ld.security.server.admin.modules.ge.entity.GeLinkEntity;
import com.ld.security.server.admin.modules.ge.vo.ModelRenderVo;
import com.ld.security.server.admin.modules.ge.vo.RenderViewVo;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 当字段类型是数字
 * 数字聚合类型存在
 * 条件在having
 * 否则where
 *
 * 如果类型是日期
 * 无论是否聚合
 * 条件在where
 *
 *
 */
public class DynWrapper extends AbstQueryWrapper implements SqlWrapper {


    //配置对象
    RenderViewVo.ModelVo config;


    List<GeFieldEntity> fields;

    public DynWrapper(RenderViewVo.ModelVo modelRenderVo, Map map) {
        this.config = modelRenderVo;
        //参数对象
        this.map = map;
        this.init();
    }

    @Override
    protected String getColumnSql() {
        StringBuffer sb = new StringBuffer();

        for (GeFieldEntity fieldEntity : fields) {

            if(sb.length() > 0){
                sb.append(",");
            }

            if(this.isWhere(fieldEntity)){

                if(fieldEntity.getFieldType() == FieldTypeConstant.date) {
                    //日期类型
                    if (fieldEntity.getDateType() == DateTypeConstant.anon) {
                        sb.append(fieldEntity.getColumnName());
                    } else {
                        sb.append("DATE_FORMAT");
                        sb.append("(");
                        sb.append(fieldEntity.getColumnName() + ",");
                        sb.append(fieldEntity.getDateType().getFormatType());
                        sb.append(")");
                    }
                }else{
                    sb.append(fieldEntity.getColumnName());
                }



            }else{
                //指标的
                if(fieldEntity.getFieldType() == FieldTypeConstant.number){
                    if(fieldEntity.getNumberType() ==  NumberTypeConstant.anon){
                        //数字类型为空，默认显示
                        sb.append(fieldEntity.getColumnName());
                    }else{
                        //否则判断聚合
                        sb.append(fieldEntity.getNumberType());
                        sb.append("(");
                        sb.append(fieldEntity.getColumnName());
                        sb.append(")");
                    }

                }
                 else{
                    sb.append(fieldEntity.getColumnName());
                }

            }


            sb.append(" as ");
            sb.append(fieldEntity.getFieldName());

        }
        this.columnSql=sb.toString();
        return columnSql;
    }

    @Override
    public String getFormSql() {
        StringBuffer sb = new StringBuffer();
        Set tableSet =  new HashSet<>();

        if(config.getLinks().isEmpty()){
            if(fields.isEmpty()){
                throw new RuntimeException("异常模型,无字段");
            }
            sb .append( fields.get(0).getTableName());
        }else{


            for (GeLinkEntity geLinkEntity : config.getLinks()) {
                if(sb.length() == 0){
                    sb.append(geLinkEntity.getTableNameX());
                    sb.append( " left join ");
                    sb.append(geLinkEntity.getTableNameY());
                    sb.append(" on ");
                    sb.append(geLinkEntity.getFieldNameX());
                    sb.append("=");
                    sb.append(geLinkEntity.getFieldNameY());
                }else{
                    sb.append( " left join ");
                    if(!tableSet.contains(geLinkEntity.getTableNameX())){
                        sb.append(geLinkEntity.getTableNameX());
                    }
                    if(!tableSet.contains(geLinkEntity.getTableNameY())){
                        sb.append(geLinkEntity.getTableNameY());
                    }
                    sb.append(" on ");
                    sb.append(geLinkEntity.getFieldNameX());
                    sb.append("=");
                    sb.append(geLinkEntity.getFieldNameY());
                }


                tableSet.add(geLinkEntity.getTableNameX());
                tableSet.add(geLinkEntity.getTableNameY());

            }



        }
        this.fromSql = sb.toString();
        return fromSql;
    }

    //条件在哪里
    private boolean isWhere(GeFieldEntity fieldEntity){
        //日期全部丢到where
        if(fieldEntity.getFieldType() == FieldTypeConstant.date){

            return true;
        }

        else if(fieldEntity.getFieldType() == FieldTypeConstant.number){
            //如果是数字，则判断是否聚合
            if(fieldEntity.getNumberType() == NumberTypeConstant.anon){
                return true;
            }
            return false;
        }else if(fieldEntity.getFieldType() == FieldTypeConstant.anon){
            //默认就是where
            return true;
        }

        return true;
    }

    @Override
    protected String getWhereSql() {

        StringBuffer sb =  new StringBuffer();

        for (GeFieldEntity fieldEntity : fields) {
             if(!isWhere(fieldEntity)){
                //条件移到having
                continue;
            }


            Object v =  map.get(fieldEntity.getFieldName());

            if(ReflectionUtil.isNull(v)){
                continue;
            }




            if(sb.length() > 0){
                sb.append(" and ");
            }
            String sql =  this.getValue(fieldEntity.getColumnName(),fieldEntity.getSqlKey(),v);
            sb.append(sql);

        }
        whereSql =sb.toString();
        return whereSql;
    }

    @Override
    protected String getValue(String name, SqlCondition sqlCondition, Object val) {
        //返回查询特殊转换

        return super.getValue(name, sqlCondition, val);
    }

    @Override
    public String getGroupSql() {
        StringBuffer sb =  new StringBuffer();

        for (GeFieldEntity fieldEntity : fields) {

            if(fieldEntity.getGroupType() == GroupTypeConstant.dimension){
                if(sb.length() > 0){
                    sb.append(" , ");
                }
                sb.append(fieldEntity.getFieldName());
            }
        }
        this.groupSql = sb.toString();
        return groupSql;
    }

    @Override
    public String getHavingSql() {
        StringBuffer sb =  new StringBuffer();
        for (GeFieldEntity fieldEntity :fields) {

             if(isWhere(fieldEntity)){
                //条件移到having
                continue;
            }

                Object v =  map.get(fieldEntity.getFieldName());
                if(ReflectionUtil.isNull(v)){
                    continue;
                }

            if(sb.length() > 0){
                sb.append(" and ");
            }
                String sql =  this.getValue(fieldEntity.getFieldName(),fieldEntity.getSqlKey(),v);
                sb.append(sql);
            }

        this.havingSql = sb.toString();
        return havingSql;
    }

    @Override
    public String getOrderSql() {
        return "";
    }

    @Override
    protected void init() {
        this.fields =  this.config.getFields().stream().filter(v -> {
            return v.getFieldType() != FieldTypeConstant.compute;
        }).collect(Collectors.toList());
        super.init();

    }
}
